package com.zllkj.mm.api.network;

import android.app.Activity;

import com.alibaba.fastjson.JSONPObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.google.gson.Gson;
import com.orhanobut.hawk.Hawk;
import com.orhanobut.logger.Logger;
import com.tencent.mm.opensdk.utils.Log;
import com.zllkj.mm.AppManager;
import com.zllkj.mm.BuildConfig;
import com.zllkj.mm.common.ClientConfig;
import com.zllkj.mm.common.L;
import com.zllkj.mm.util.EmptyUtils;
import com.zllkj.mm.util.JsonUtil;
import com.zllkj.mm.util.common.NetworkUtils;

import org.json.JSONObject;

import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.UnsupportedCharsetException;
import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

import okhttp3.HttpUrl;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okio.Buffer;
import okio.BufferedSource;

import static okhttp3.internal.http.HttpHeaders.hasBody;

public class SessionInterceptor implements Interceptor {
    private final Charset UTF8 = Charset.forName("UTF-8");


    @Override
    public Response intercept(Chain chain) throws IOException {
        Request originalRequest = chain.request();
        HttpUrl originalHttpUrl = originalRequest.url();

        try {
            Activity activity = AppManager.getAppManager().currentActivity();
            if (!NetworkUtils.isAvailable(activity)) {
                activity.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        L.showToast("当前无网络!");
                    }
                });
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        HttpUrl url = originalHttpUrl.newBuilder()
//                .addQueryParameter("session_id", MyApp.getInstance().getSessionId())
                .build();

        RequestBody oldBody = originalRequest.body();
        Buffer buffer = new Buffer();
        oldBody.writeTo(buffer);
        String strOldBody = buffer.readUtf8();
        MediaType mediaType = MediaType.parse("text/plain; charset=utf-8");

        String clientKey="app";
        int nonce =(int)((Math.random()*9+1)*100000);
        String timestamp=String.valueOf(System.currentTimeMillis());

        String strNewBody = getSignature1(strOldBody,clientKey,nonce,timestamp);
        StringBuffer buffer2=new StringBuffer();
        buffer2.append("{");
        buffer2.append("\"sign\":\""+strNewBody+"\""+",");
        buffer2.append("\"clientKey\":\"app\""+",");
        buffer2.append("\"nonce\":\""+nonce+"\""+",");
        buffer2.append("\"timestamp\":\""+timestamp+"\""+",");
        buffer2.append(strOldBody.substring(1));


        RequestBody body = RequestBody.create(mediaType, buffer2.toString());
//        originalRequest = originalRequest
//                .newBuilder()
//                .header("Content-Type", body.contentType().toString())
//                .header("Content-Length", String.valueOf(body.contentLength()))
//                .method(originalRequest.method(), body).build();
//        return chain.proceed(originalRequest);
//        Request request = originalRequest.newBuilder()
//                .url(url)
//                .addHeader(!EmptyUtils.isEmpty(Hawk.get(L.token)) ? "token" : "null", "" + Hawk.get(L.token))
//                .method(originalRequest.method(), body)
//                .build();
//        return chain.proceed(request);

        Request request = originalRequest.newBuilder()
                .url(url)
                .addHeader(!EmptyUtils.isEmpty(Hawk.get(L.token)) ? "token" : "null", "" + Hawk.get(L.token))
                .method(originalRequest.method(), body)
                .build();

        Response resp = chain.proceed(request);
        //打印日志
        if (BuildConfig.DEBUG)
            logBody(resp,request.body());

        return resp;
    }

    private void logBody(Response response , RequestBody requestBody) throws IOException {
        ResponseBody responseBody = response.body();
        String rBody = null;
        String reqBodyString = "";
        if(hasBody(response)) {
            BufferedSource source = responseBody.source();
            source.request(Long.MAX_VALUE); // Buffer the entire body.
            Buffer buf = source.buffer();

            Charset charset = UTF8;
            MediaType contentType = responseBody.contentType();
            if (contentType != null) {
                try {
                    charset = contentType.charset(UTF8);
                } catch (UnsupportedCharsetException e) {
                    e.printStackTrace();
                }
            }
            rBody = buf.clone().readString(charset);
        }

        if(requestBody != null) {
            Buffer buffer = new Buffer();
            requestBody.writeTo(buffer);

            Charset charset = UTF8;
            MediaType contentType = requestBody.contentType();
            if (contentType != null) {
                charset = contentType.charset(UTF8);
            }
            reqBodyString = buffer.readString(charset);
        }

        Logger.e("收到响应 %s%s %ss\n请求url：%s\n请求body：%s\n响应body：%s",
                response.code(), response.message(), "", response.request().url(), reqBodyString, rBody);
    }

    private static void specialHandleKey(String params){
        // {"pageSize":20,"shoppingCartGoodsIds":"320,316"}
    }

    /**
     * 签名生成算法
     * HashMap<String,String> params 请求参数集，所有参数必须已转换为字符串类型
     * String secret 签名密钥
     * @return 签名
     * @throws IOException
     */
    public static String getSignature1(String params,String clientKey,int nonce,String timestamp) throws IOException{

        ObjectMapper mapper = new ObjectMapper();
        HashMap<String,Object> coverMap = mapper.readValue(params,HashMap.class);

        //以逗号分隔String参数


        List<String> list=new ArrayList<String>();
        //将参数的符合修改为接口文档标准并加入list
        if (coverMap != null) {
            for(String key:coverMap.keySet()){
                list.add(key+"=" + coverMap.get(key));
            }
        }
        list.add("clientKey="+clientKey);
        list.add("nonce="+nonce);
        list.add("timestamp="+timestamp);
        //字段升序排列
        List<String> sorted = asSortedList(list);
        sorted.add("key="+ ClientConfig.KEY);
        StringBuffer buffer=new StringBuffer();
        for (int i=0;i<sorted.size();i++){
            if(!"".equals(sorted.get(i).toString())){
                buffer.append(sorted.get(i)+"&");
            }
        }
        String result=buffer.toString().substring(0,buffer.toString().length() - 1);
        // 使用MD5对待签名串求签
        byte[] bytes = null;
        try { MessageDigest md5 = MessageDigest.getInstance("MD5");
            bytes = md5.digest(result.getBytes("UTF-8"));
        } catch (GeneralSecurityException ex) {
            throw new IOException(ex);
        }

        // 将MD5输出的二进制结果转换为小写的十六进制
        StringBuilder sign = new StringBuilder();
        for (int i = 0; i < bytes.length; i++) {
            String hex = Integer.toHexString(bytes[i] & 0xFF);
            if (hex.length() == 1) {
                sign.append("0");
            }
            sign.append(hex);
        }
        return sign.toString();
    }

    public static String formatBizQueryParaMap(Map<String,String> paraMap){
        Set<String> keys = paraMap.keySet();
        List<String> sorted = asSortedList(keys);
        StringBuffer buffer=new StringBuffer();
        for(String key : sorted){
            buffer.append(key+"="+paraMap.get(key)+"&");
        }
        String result = "";
        if (buffer.length() > 0) {
            result = buffer.substring(0, buffer.length()-1);
        }
        return result;
    }

    public static <T extends Comparable<? super T>> List<T> asSortedList(Collection<T> c) {
        List<T> list = new ArrayList<T>(c);
        java.util.Collections.sort(list);
        return list;
    }


    /**
     * 签名生成算法
     * HashMap<String,String> params 请求参数集，所有参数必须已转换为字符串类型
     * String secret 签名密钥
     * @return 签名
     * @throws IOException
     */
    public static String getSignature(HashMap<String,String> params, String secret) throws IOException
    {
        // 先将参数以其参数名的字典序升序进行排序
        Map<String, String> sortedParams = new TreeMap<String, String>(params);
        Set<Map.Entry<String, String>> entrys = sortedParams.entrySet();

        // 遍历排序后的字典，将所有参数按"key=value"格式拼接在一起
        StringBuilder basestring = new StringBuilder();
        for (Map.Entry<String, String> param : entrys) {
            basestring.append(param.getKey()).append("=").append(param.getValue());
        }
        basestring.append(secret);

        // 使用MD5对待签名串求签
        byte[] bytes = null;
        try {
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            bytes = md5.digest(basestring.toString().getBytes("UTF-8"));
        } catch (GeneralSecurityException ex) {
            throw new IOException(ex);
        }

        // 将MD5输出的二进制结果转换为小写的十六进制
        StringBuilder sign = new StringBuilder();
        for (int i = 0; i < bytes.length; i++) {
            String hex = Integer.toHexString(bytes[i] & 0xFF);
            if (hex.length() == 1) {
                sign.append("0");
            }
            sign.append(hex);
        }
        return sign.toString();
    }

}